#import "PinNoteViewer.h"

// Shared instance of PinNoteViewer
static PinNoteViewer* sharedPinNoteViewer = nil;

/**
 * A PinNoteViewer is an object representing the view for displaying
 * pin note information. It also provides the utility for editing, 
 * relocating, and deleting the given pin note.
 *
 * @author      James Lin
 * @version     1.3.7
 * @since       1.3.0
 */
@implementation PinNoteViewer

@synthesize pinTitle;
@synthesize pinDesc;

/**
 * Retrieve the shared instance of the pin note viewer.
 *
 * @return  the shared instance of PinNoteViewer
 */
+ (PinNoteViewer*)sharedPinNoteViewer {
	@synchronized(self) {
		if (sharedPinNoteViewer == nil) {
			sharedPinNoteViewer = [[PinNoteViewer alloc] init];
		}
		return sharedPinNoteViewer;
	}
}

/**
 * Allocate the pin note viewer.
 *
 * @return  the newly allocated shared instance of PinNoteViewer
 */
+ (id) alloc {
	@synchronized(self) {
		sharedPinNoteViewer = [super alloc];
		return sharedPinNoteViewer;
	}
}

/**
 * Retrieve a copy of the pin note viewer.
 *
 * @return  the shared instance of PinNoteViewer
 */
+ (id) copy {
	@synchronized(self) {
		return sharedPinNoteViewer;
	}
}

/**
 * Helper method to create the viewer for the pin note details.
 */
- (void)buildViewer {
	// Create the scrollable view to contain the details form
	inputView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 
															   VIEW_WIDTH, 
															   VIEW_HEIGHT)];
	inputView.contentSize = CGSizeMake(VIEW_WIDTH, VIEW_HEIGHT+1);
	inputView.backgroundColor = [UIColor groupTableViewBackgroundColor];
	
	// Create the pin title label
	NSString* titleLabelMsg = @"Title:";
	UILabel* titleLabel;
	titleLabel = [GraphicsUtilities getLabelResizedToText:titleLabelMsg 
													 font:[UIFont boldSystemFontOfSize:17] 
												textColor:nil 
												 hPadding:10
												 vPadding:5 
												   height:20];
	[titleLabel setTextColor:[UIColor colorWithRed:0.3 green:0.337  blue:0.375 alpha:1]];
	[titleLabel setShadowColor:[UIColor whiteColor]];
	[titleLabel setShadowOffset:CGSizeMake(0, 1)];
	[inputView addSubview:titleLabel];
	[titleLabel release];
	
	// Create the text field for the pin's title
	CGRect titleFrame = CGRectMake(10, 30, VIEW_WIDTH-20, 40);
	titleField = [[UITextField alloc] initWithFrame:titleFrame];
	titleField.borderStyle = UITextBorderStyleBezel;
	titleField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
	titleField.backgroundColor = [UIColor lightTextColor];
	titleField.font = [UIFont systemFontOfSize:14.0];
	titleField.layer.cornerRadius = 8;
	titleField.layer.borderWidth = 1;
	titleField.autocorrectionType = UITextAutocorrectionTypeNo;
	titleField.delegate = self;
	titleField.tag = 0;
	[inputView addSubview:titleField];
	
	// Create the pin notes label
	CGRect descLabelFrame = CGRectMake(10, titleField.frame.size.height+45, 
									   VIEW_WIDTH-20, 20);
	NSString* descLabelMsg = @"Notes:";
	UILabel* descLabel;
	descLabel = [GraphicsUtilities getLabelResizedToText:descLabelMsg 
													font:[UIFont boldSystemFontOfSize:17] 
											   textColor:nil 
												hPadding:10
												vPadding:5 
												  height:20];
	[descLabel setTextColor:[UIColor colorWithRed:0.3 green:0.337 blue:0.375 alpha:1]];
	[descLabel setShadowColor:[UIColor whiteColor]];
	[descLabel setShadowOffset:CGSizeMake(0, 1)];
	[descLabel setFrame:descLabelFrame];
	[inputView addSubview:descLabel];
	[descLabel release];
	
	// Create the text view for the pin's notes
	CGRect descFrame = CGRectMake(10, titleField.frame.size.height+70, 
								  VIEW_WIDTH-20, 320);
	descView = [[UITextView alloc] initWithFrame:descFrame];
	descView.backgroundColor = [UIColor lightTextColor];
	descView.font = [UIFont systemFontOfSize:14.0];
	descView.scrollEnabled = NO;
	descView.layer.cornerRadius = 8;
	descView.layer.borderWidth = 1;
	descView.contentInset = UIEdgeInsetsMake(3, 5, 3, 5);
	descView.autocorrectionType = UITextAutocorrectionTypeNo;
	descView.delegate = self;
	descView.tag = 1;
	[inputView addSubview:descView];
	[descView release];
	
	[self.view addSubview:inputView];
	
	// Create the toolbar for the pin note viewer
	toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, VIEW_HEIGHT-44, 
														  VIEW_WIDTH, 44)];
	toolbar.barStyle = UIBarStyleBlack;
}

/**
 * Initialize the shared instance of the pin note viewer.
 *
 * @return  the initialized pin note viewer
 */
- (id)init {
	if (self = [super init]) {
		[self buildViewer];
		isEditOnly = NO;
	}
	return self;
}

/**
 * Display the pin note viewer.
 *
 * @param theDelegate  the delegate handling pin note viewer events
 * @param isNew        whether the display request is only to add a new pin note
 */
- (void)displayWithDelegate:(id<PinNoteViewerDelegate>)theDelegate 
			   isNewPinNote:(BOOL)isNew {
	delegate = theDelegate;
	isNewPinNote = isNew;
	
	// Reset fields if new pin
	if (!isNewPinNote) {
		[self setEditable];
	} else {
		//self.pinTitle = @"";
		//self.pinDesc = @"";
		
		if ([self.pinTitle length] > 0) {
			isEditOnly = YES;
		}
	}
	
	self.title = @"Pin Details";
	titleField.text = self.pinTitle;
	descView.text = self.pinDesc;
	
	//UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
	//																			  target:self 
	//																			  action:@selector(handleViewCancel)];
	UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
																				target:self 
																				action:@selector(handleViewDone)];
	//[self.navigationItem setLeftBarButtonItem:cancelButton];
	//self.navigationItem.leftBarButtonItem.title = @"Cancel";
	//self.navigationItem.leftBarButtonItem.target = self;
	//self.navigationItem.leftBarButtonItem.action = @selector(handleViewCancel);
	[self.navigationItem setRightBarButtonItem:doneButton];
	
	//[cancelButton release];
	[doneButton release];
	
	[titleField becomeFirstResponder];
	
	// Show the pin note viewer
	[[delegate getNavController] pushViewController:self animated:YES];
}

/**
 * Display the given pin note.
 *
 * @param pinNote      the pin note of which to display details
 * @param theDelegate  the delegate handling pin note viewer events
 */
- (void)displayPinNote:(AddressAnnotation*)pinNote 
			  delegate:(id<PinNoteViewerDelegate>)theDelegate {
	currentPinNote = pinNote;
	self.pinTitle = pinNote.title;
	self.pinDesc = pinNote.subtitle;
	
	[self displayWithDelegate:theDelegate isNewPinNote:NO];
	[titleField resignFirstResponder];
}

/**
 * Set the pin note viewer to editor mode.
 */
- (void)setEditable {
	// Make room for the toolbar
	[inputView setFrame:CGRectMake(0, 0, VIEW_WIDTH, VIEW_HEIGHT-44)];
	
	// Create the toolbar buttons
	UIBarButtonItem* deleteButton;
	deleteButton = [[UIBarButtonItem alloc] initWithTitle:@"Delete" 
													style:UIBarButtonItemStyleBordered 
												   target:self
												   action:@selector(confirmPinDelete)];
	UIBarButtonItem* relocateButton;
	relocateButton = [[UIBarButtonItem alloc] initWithTitle:@"Relocate on Map" 
													  style:UIBarButtonItemStyleBordered
													 target:self 
													 action:@selector(handlePinRelocate)];
	UIBarButtonItem* spacer;
	spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
														   target:nil
														   action:nil];
	
	// Add the buttons to the toolbar
	NSArray* buttons = [NSArray arrayWithObjects:
						spacer, deleteButton, relocateButton, spacer, nil];
	[toolbar setItems:buttons animated:NO];
	[self.view addSubview:toolbar];
	
	[deleteButton release];
	[relocateButton release];
	[spacer release];
}

/**
 * Exit the input pin details view via a cancel.
 */
- (void)handleViewCancel {
	isEditOnly = NO;
	
	// Remove the input keyboard
	[titleField becomeFirstResponder];
	[titleField resignFirstResponder];
	
	// Hide the pin note viewer
	[[delegate getNavController] popViewControllerAnimated:YES];
	
	// Remove the navigation bar buttons
	[self.navigationItem setLeftBarButtonItem:nil];
	[self.navigationItem setRightBarButtonItem:nil];
}

/**
 * Process the done request from the input pin details view.
 */
- (void)handleViewDone {
	if ([titleField.text length] > 0) {
		[titleField becomeFirstResponder];
		[titleField resignFirstResponder];
		
		// Notify accordingly that the pin note viewer has completed its task
		if (isNewPinNote) {
			if (isEditOnly) {
				[delegate handleEditedPinNoteWithTitle:self.pinTitle notes:self.pinDesc];
			} else {
				[delegate handleNewPinNoteWithTitle:self.pinTitle notes:self.pinDesc];
			}
			[[delegate getNavController] popViewControllerAnimated:YES];
		} else {
			currentPinNote.title = self.pinTitle;
			currentPinNote.subtitle = self.pinDesc;
			[delegate requestSavePinNote:currentPinNote];
			//[[delegate getNavController] popViewControllerAnimated:YES];
		}
	} else {
		// Do not allow a pin note with an empty title
		[GraphicsUtilities displayAlertWithTitle:@"Please enter a title for the pin." 
										 message:nil];
		[titleField becomeFirstResponder];
	}
	
	isEditOnly = NO;
}

/**
 * Handle a pin delete request.
 */
- (void)handlePinDelete {
	[delegate requestDeletePinNote:currentPinNote];
	[[delegate getNavController] popViewControllerAnimated:YES];
}

/**
 * Handle a pin relocate request.
 */
- (void)handlePinRelocate {
	[delegate requestRelocatePinNote:currentPinNote];
	[[delegate getNavController] popViewControllerAnimated:YES];
}

/**
 * Get confirmation for a pin delete request.
 */
- (void)confirmPinDelete {
	NSString* msg = @"Are you sure you want to delete this pin note?";
	[GraphicsUtilities displayConfirmationWithTitle:msg
											message:nil 
												tag:0 
										   delegate:self];
}

/**
 * Handle the confirmation of the alert view.
 *
 * @see  UIAlertViewDelegate
 */
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
	switch (alertView.tag) {
		case 0:
			if (buttonIndex == 0) {
				[self handlePinDelete];
			}
			break;
	}
}

/**
 * Set up the keyboard return key for the title field.
 */
- (BOOL)textFieldShouldBeginEditing:(UITextField*)textField {
	switch ([textField tag]) {
		case 0:
			[textField setReturnKeyType:UIReturnKeyNext];
			break;
	}
	return YES;
}

/**
 * Limit the title text to 50 characters.
 */
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range 
													  replacementString:(NSString*)string {
	switch ([textField tag]) {
		case 0:
			if ([textField.text length] - range.length + string.length > 50) {
				return NO;
			}
			break;
	}
	
	return YES;
}

/**
 * Limit the notes text to 500 characters.
 */
- (BOOL)textView:(UITextView*)textView shouldChangeTextInRange:(NSRange)range 
											   replacementText:(NSString*)text {
	switch ([textView tag]) {
		case 1:
			if ([textView.text length] - range.length + text.length > 500) {
				return NO;
			}
			break;
	}
	
	return YES;
}

/**
 * Save the information in the title field.
 */
- (void)textFieldDidEndEditing:(UITextField *)textField {
	switch ([textField tag]) {
		case 0:
			self.pinTitle = [[textField text] 
							 stringByTrimmingCharactersInSet:
							 [NSCharacterSet whitespaceAndNewlineCharacterSet]];
			break;
	}
}

/**
 * Save the information in the notes text view.
 */
- (void)textViewDidEndEditing:(UITextView *)textView {
	switch ([textView tag]) {
		case 1:
			self.pinDesc = [[textView text] 
							stringByTrimmingCharactersInSet:
							[NSCharacterSet whitespaceAndNewlineCharacterSet]];
			break;
	}
}

/**
 * Check and attempt to initiate the search upon field return.
 */
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
	if ([textField returnKeyType] != UIReturnKeyDone) {
		NSInteger nextTag = [textField tag] + 1;
		UIView *nextField = [inputView viewWithTag:nextTag];
		
		[nextField becomeFirstResponder];
	}
	
	return NO;
}

/**
 * Deallocate the pin note viewer.
 */
- (void)dealloc {
	[pinTitle release], pinTitle = nil;
	[pinDesc release], pinDesc = nil;
	[titleField release], titleField = nil;
	[descView release], descView = nil;
	[inputView release], inputView = nil;
	[toolbar release], toolbar = nil;
	delegate = nil;
	[sharedPinNoteViewer release], sharedPinNoteViewer = nil;
	[super dealloc];
}

@end